#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JAR文件安装脚本
支持使用libs目录下的pom.xml文件，保留完整的依赖信息
"""

import os
import json
import subprocess
import logging
import shutil
import sys
from pathlib import Path
from typing import Dict, List, Tuple
import xml.etree.ElementTree as ET

# 创建日志目录
log_dir = Path('artifacts')
log_dir.mkdir(exist_ok=True)

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('artifacts/jar_installation.log', encoding='utf-8')
    ]
)

def clean_artifacts(jar_config: dict) -> None:
    """清理本地Maven仓库中的构件"""
    local_repo = get_maven_local_repository()
    cleaned_count = 0
    failed_count = 0

    logging.info("\n开始清理本地Maven仓库...")
    for jar_path, coords in jar_config.items():
        group_id = coords['groupId']
        artifact_id = coords['artifactId']
        version = coords['version']

        # 构建构件目录路径
        group_path = group_id.replace('.', '/')
        artifact_dir = local_repo / group_path / artifact_id

        try:
            if artifact_dir.exists():
                # 如果指定了版本，只删除该版本
                if version:
                    version_dir = artifact_dir / version
                    if version_dir.exists():
                        shutil.rmtree(version_dir)
                        cleaned_count += 1
                        logging.info(f"✅ 已删除: {group_id}:{artifact_id}:{version}")
                    else:
                        logging.warning(f"⚠️ 版本目录不存在: {version_dir}")
                # 如果没有指定版本，删除整个构件目录
                else:
                    shutil.rmtree(artifact_dir)
                    cleaned_count += 1
                    logging.info(f"✅ 已删除: {group_id}:{artifact_id}")
        except Exception as e:
            failed_count += 1
            logging.error(f"❌ 删除失败 {group_id}:{artifact_id}:{version}: {str(e)}")

    logging.info(f"\n清理完成:")
    logging.info(f"成功清理: {cleaned_count} 个构件")
    logging.info(f"清理失败: {failed_count} 个构件")

def check_maven_installation() -> bool:
    """检查Maven是否已安装"""
    commands = [['mvn', '--version']]

    # Windows系统添加额外的检查命令
    if sys.platform.startswith('win'):
        commands.insert(0, ['mvn.cmd', '--version'])

    for cmd in commands:
        try:
            result = subprocess.run(cmd,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    universal_newlines=True)
            if result.returncode == 0:
                return True
        except FileNotFoundError:
            continue
    return False

def get_maven_executable() -> str:
    """获取适用于当前系统的Maven可执行文件"""
    if sys.platform.startswith('win'):
        # 在Windows上优先尝试mvn.cmd
        if check_command_exists('mvn.cmd'):
            return 'mvn.cmd'
        elif check_command_exists('mvn'):
            return 'mvn'
    else:
        # 在Linux/macOS上使用mvn
        if check_command_exists('mvn'):
            return 'mvn'

    # 如果找不到可执行文件，返回默认值
    return 'mvn' if not sys.platform.startswith('win') else 'mvn.cmd'

def check_command_exists(command: str) -> bool:
    """检查命令是否存在"""
    try:
        subprocess.run([command, '--version'],
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE,
                       check=True)
        return True
    except (FileNotFoundError, subprocess.CalledProcessError):
        return False

def get_maven_local_repository() -> Path:
    """获取Maven本地仓库路径"""
    try:
        # Windows系统优先使用mvn.cmd
        commands = [['mvn', 'help:evaluate', '-Dexpression=settings.localRepository', '-q', '-DforceStdout']]
        if sys.platform.startswith('win'):
            commands.insert(0, ['mvn.cmd', 'help:evaluate', '-Dexpression=settings.localRepository', '-q',
                                '-DforceStdout'])

        for cmd in commands:
            try:
                result = subprocess.run(cmd,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE,
                                        universal_newlines=True)
                if result.returncode == 0:
                    return Path(result.stdout.strip())
            except FileNotFoundError:
                continue

        # 默认Maven本地仓库路径
        return Path.home() / '.m2' / 'repository'
    except Exception:
        return Path.home() / '.m2' / 'repository'

def print_installed_artifacts(jar_config: dict):
    """打印已安装的构件信息"""
    logging.info("\n已安装的构件信息:")
    logging.info("=" * 80)
    logging.info(f"{'GroupId':<40} {'ArtifactId':<30} {'Version':<20}")
    logging.info("-" * 80)

    for jar_path, coords in jar_config.items():
        group_id = coords['groupId']
        artifact_id = coords['artifactId']
        version = coords['version']

        # 检查pom文件是否存在
        local_repo = get_maven_local_repository()
        group_path = group_id.replace('.', '/')
        pom_path = local_repo / group_path / artifact_id / version / f"{artifact_id}-{version}.pom"

        if pom_path.exists():
            status = "✅"
        else:
            status = "❌"

        logging.info(f"{group_id:<40} {artifact_id:<30} {version:<20} {status}")

    logging.info("=" * 80)

def install_jar(jar_path: Path, coordinates: dict, libs_dir: Path, mvn_exec: str) -> Tuple[bool, str]:
    """安装单个jar文件到Maven本地仓库"""
    artifact_id = coordinates["artifactId"]
    version = coordinates["version"]

        # 检查配置中是否指定了pomFile
    if "pomFile" in coordinates:
        pom_filename = coordinates["pomFile"]
        pom_path = libs_dir / pom_filename

        if pom_path.exists():
            # 使用配置指定的pom.xml文件
            cmd = [
                mvn_exec, 'install:install-file',
                f'-Dfile={jar_path}',
                f'-DpomFile={pom_path}',
                f'-DgroupId={coordinates["groupId"]}',
                f'-DartifactId={coordinates["artifactId"]}',
                f'-Dversion={coordinates["version"]}',
                '-Dpackaging=jar'
            ]
            install_method = f"使用配置指定的pom.xml: {pom_filename}"
            logging.info(f"🔍 使用配置指定的pom.xml文件: {pom_path}")
        else:
            logging.error(f"❌ 配置指定的pom.xml文件不存在: {pom_path}")
            return False, f"配置指定的pom.xml文件不存在: {pom_filename}"
    else:
        # 没有配置pomFile，使用生成pom.xml的方式
        cmd = [
            mvn_exec, 'install:install-file',
            f'-Dfile={jar_path}',
            f'-DgroupId={coordinates["groupId"]}',
            f'-DartifactId={coordinates["artifactId"]}',
            f'-Dversion={coordinates["version"]}',
            '-Dpackaging=jar',
            '-DgeneratePom=true'
        ]
        install_method = "生成简化pom.xml"
        logging.info(f"📝 未配置pomFile，将生成简化的pom.xml")

    try:
        # 在Windows上使用shell=True确保命令正确执行
        use_shell = sys.platform.startswith('win')
        result = subprocess.run(cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                universal_newlines=True,
                                shell=use_shell)
        if result.returncode == 0:
            return True, f"安装成功 ({install_method})"
        else:
            return False, f"安装失败: {result.stderr}"
    except Exception as e:
        return False, f"安装异常: {str(e)}"

def main():
    # 检查命令行参数
    if len(sys.argv) > 1 and sys.argv[1] == 'clean':
        should_clean = True
    else:
        should_clean = False

    # 获取脚本所在目录
    script_dir = Path(__file__).parent.resolve()
    backend_dir = script_dir.parent
    libs_dir = backend_dir / 'backend' / 'libs'
    config_file = script_dir / 'jar_config.json'

    if not config_file.exists():
        logging.error(f"❌ 配置文件不存在: {config_file}")
        logging.info("请先运行 generate_jar_config.py 生成配置文件")
        return

    if not libs_dir.exists():
        logging.error(f"❌ 源目录不存在: {libs_dir}")
        return

    # 检查Maven是否安装
    if not check_maven_installation():
        logging.error("❌ Maven未安装，请先安装Maven")
        return

    # 读取配置文件
    with open(config_file, 'r', encoding='utf-8') as f:
        jar_config = json.load(f)

    # 如果是清理模式，执行清理后退出
    if should_clean:
        clean_artifacts(jar_config)
        return

    # 获取适用于当前系统的Maven可执行文件
    mvn_exec = get_maven_executable()
    logging.info(f"使用Maven可执行文件: {mvn_exec}")

    success_list = []
    failed_list = []
    skipped_list = []

    logging.info("🚀 开始安装JAR文件...")
    logging.info("📋 优先使用libs目录下的pom.xml文件")
    logging.info("=" * 60)

    # 安装所有jar包
    for relative_path, coords in jar_config.items():
        jar_path = libs_dir / relative_path
        if not jar_path.exists():
            logging.warning(f"⚠️ 文件不存在: {jar_path}")
            skipped_list.append(relative_path)
            continue

        logging.info(f"📦 正在安装: {relative_path}")
        success, message = install_jar(jar_path, coords, libs_dir, mvn_exec)

        if success:
            success_list.append(relative_path)
            logging.info(f"✅ {relative_path}: {message}")
        else:
            failed_list.append(relative_path)
            logging.error(f"❌ {relative_path}: {message}")

    # 输出安装结果
    logging.info(f"\n📊 安装总结:")
    logging.info(f"成功安装: {len(success_list)} 个文件")
    logging.info(f"安装失败: {len(failed_list)} 个文件")
    logging.info(f"已跳过: {len(skipped_list)} 个文件")

    # 打印已安装的构件信息
    print_installed_artifacts(jar_config)

    if failed_list:
        logging.info("\n❌ 安装失败的jar包:")
        for jar_path in failed_list:
            logging.info(f"  - {jar_path}")

    if skipped_list:
        logging.info("\n⏭️ 跳过的jar包:")
        for jar_path in skipped_list:
            logging.info(f"  - {jar_path}")

    # 提供使用建议
    logging.info("\n💡 使用建议:")
    logging.info(f"  - 将pom.xml文件放在libs目录: {libs_dir}")
    logging.info("  - 在jar_config.json中添加pomFile字段指定pom.xml文件")
    logging.info("    例如: \"pomFile\": \"anysdk-spring-boot-starter-1.0.1.pom.xml\"")
    logging.info("  - 配置了pomFile会保留完整的依赖信息")
    logging.info("  - 未配置pomFile会生成简化的pom.xml")
    logging.info("  - 使用 'python3 init_jars.py clean' 清理本地仓库")

if __name__ == '__main__':
    main()